use async_trait::async_trait;
use rustcloud_core::{ServiceRegistry, ServiceInstance, ServiceResult, ServiceRegistryEvent, ServiceError};
use rustcloud_core::RegistryType;
use crate::nacos::NacosRegistry;
use crate::consul::ConsulRegistry;
use crate::eureka::EurekaRegistry;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use serde::{Deserialize, Serialize};

/// 注册中心配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RegistryConfig {
    /// 注册中心类型
    pub registry_type: RegistryType,
    /// 服务器地址
    pub server_addr: String,
    /// 命名空间（Nacos使用）
    pub namespace: Option<String>,
    /// 分组（Nacos使用）
    pub group: Option<String>,
    /// 数据中心（Consul使用）
    pub datacenter: Option<String>,
    /// 连接超时时间（毫秒）
    pub timeout: u64,
    /// 重试次数
    pub retry_count: u32,
    /// 重试间隔（毫秒）
    pub retry_interval: u64,
}

impl RegistryConfig {
    /// 创建新的注册中心配置
    pub fn new(registry_type: RegistryType, server_addr: impl Into<String>) -> Self {
        Self {
            registry_type,
            server_addr: server_addr.into(),
            namespace: None,
            group: None,
            datacenter: None,
            timeout: 5000,
            retry_count: 3,
            retry_interval: 1000,
        }
    }
    
    /// 设置命名空间
    pub fn with_namespace(mut self, namespace: impl Into<String>) -> Self {
        self.namespace = Some(namespace.into());
        self
    }
    
    /// 设置分组
    pub fn with_group(mut self, group: impl Into<String>) -> Self {
        self.group = Some(group.into());
        self
    }
    
    /// 设置数据中心
    pub fn with_datacenter(mut self, datacenter: impl Into<String>) -> Self {
        self.datacenter = Some(datacenter.into());
        self
    }
    
    /// 设置超时时间
    pub fn with_timeout(mut self, timeout: u64) -> Self {
        self.timeout = timeout;
        self
    }
}

impl Default for RegistryConfig {
    fn default() -> Self {
        Self::new(RegistryType::Nacos, "127.0.0.1:8848")
    }
}

/// 内存实现的注册中心，用于测试和开发环境
pub struct InMemoryRegistry {
    services: Arc<RwLock<HashMap<String, Vec<ServiceInstance>>>>,
}

impl InMemoryRegistry {
    pub fn new() -> Self {
        Self {
            services: Arc::new(RwLock::new(HashMap::new())),
        }
    }
}

#[async_trait]
impl ServiceRegistry for InMemoryRegistry {
    async fn register(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let mut services = self.services.write().await;
        let instances = services
            .entry(instance.service_id.clone())
            .or_insert_with(Vec::new);
        
        // 检查是否已经存在相同的服务实例
        if !instances.iter().any(|i| i.host == instance.host && i.port == instance.port) {
            instances.push(instance);
        }
        
        Ok(())
    }

    async fn deregister(&self, instance: ServiceInstance) -> ServiceResult<()> {
        let mut services = self.services.write().await;
        if let Some(instances) = services.get_mut(&instance.service_id) {
            instances.retain(|i| !(i.host == instance.host && i.port == instance.port));
        }
        Ok(())
    }

    async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        let services = self.services.read().await;
        let instances = services
            .get(service_name)
            .cloned()
            .unwrap_or_default();
        
        // 只返回健康的服务实例
        let healthy_instances: Vec<ServiceInstance> = instances
            .into_iter()
            .filter(|i| i.healthy)
            .collect();
            
        Ok(healthy_instances)
    }

    async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        // 对于内存注册中心，直接返回所有实例
        self.discover(service_name).await
    }

    async fn watch(&self, service_name: &str) -> ServiceResult<Box<dyn rustcloud_core::ServiceWatcher + Send>> {
        Ok(Box::new(InMemoryWatcher::new(service_name.to_string())))
    }
}

pub struct InMemoryWatcher {
    _service_name: String,
}

impl InMemoryWatcher {
    pub fn new(service_name: String) -> Self {
        Self { _service_name: service_name }
    }
}

#[async_trait]
impl rustcloud_core::ServiceWatcher for InMemoryWatcher {
    async fn next_event(&mut self) -> ServiceResult<ServiceRegistryEvent> {
        // 内存注册中心不支持实时事件，这里返回一个阻塞的等待
        tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await;
        Err(rustcloud_core::ServiceError::RegistryError("不支持事件监听".to_string()))
    }
}

/// 注册中心工厂，根据配置创建具体的注册中心实例
pub struct RegistryFactory;

impl RegistryFactory {
    pub fn create(config: RegistryConfig) -> ServiceResult<Arc<dyn ServiceRegistry>> {
        match config.registry_type {
            RegistryType::Nacos => {
                let registry = NacosRegistry::new(config)?;
                Ok(Arc::new(registry))
            }
            RegistryType::Consul => {
                let registry = ConsulRegistry::new(config)?;
                Ok(Arc::new(registry))
            }
            RegistryType::Eureka => {
                let registry = EurekaRegistry::new(config)?;
                Ok(Arc::new(registry))
            }
        }
    }
}

/// 组合注册中心，支持多注册中心同时工作
pub struct CompositeRegistry {
    registries: HashMap<String, Arc<dyn ServiceRegistry>>,
}

impl CompositeRegistry {
    pub fn new() -> Self {
        Self {
            registries: HashMap::new(),
        }
    }

    pub fn add_registry(
        &mut self, name: String, registry: Arc<dyn ServiceRegistry>
    ) {
        self.registries.insert(name, registry);
    }
}

#[async_trait]
impl ServiceRegistry for CompositeRegistry {
    async fn register(
        &self, instance: ServiceInstance
    ) -> ServiceResult<()> {
        let mut errors = Vec::new();
        for registry in self.registries.values() {
            match registry.register(instance.clone()).await {
                Ok(_) => continue,
                Err(e) => errors.push(e),
            }
        }
        if errors.is_empty() {
            Ok(())
        } else {
            Err(ServiceError::RegistryError(format!("Failed to register in all registries: {:?}", errors)))
        }
    }

    async fn deregister(
        &self, instance: ServiceInstance
    ) -> ServiceResult<()> {
        let mut errors = Vec::new();
        for registry in self.registries.values() {
            match registry.deregister(instance.clone()).await {
                Ok(_) => continue,
                Err(e) => errors.push(e),
            }
        }
        if errors.is_empty() {
            Ok(())
        } else {
            Err(ServiceError::RegistryError(format!("Failed to deregister in all registries: {:?}", errors)))
        }
    }

    async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        let mut all_instances = Vec::new();
        let mut errors = Vec::new();
        for registry in self.registries.values() {
            match registry.discover(service_name).await {
                Ok(instances) => all_instances.extend(instances),
                Err(e) => errors.push(e),
            }
        }
        if !all_instances.is_empty() || errors.is_empty() {
            Ok(all_instances)
        } else {
            Err(ServiceError::RegistryError(format!("Failed to discover from all registries: {:?}", errors)))
        }
    }

    async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        let mut healthy_instances = Vec::new();
        let mut errors = Vec::new();
        for registry in self.registries.values() {
            match registry.health_check(service_name).await {
                Ok(instances) => healthy_instances.extend(instances),
                Err(e) => errors.push(e),
            }
        }
        Ok(healthy_instances)
    }

    async fn watch(
        &self, service_name: &str
    ) -> ServiceResult<Box<dyn rustcloud_core::ServiceWatcher + Send>> {
        // 返回第一个注册中心的观察者
        if let Some(registry) = self.registries.values().next() {
            registry.watch(service_name).await
        } else {
            Err(ServiceError::RegistryError("No registries configured".to_string()))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use rustcloud_core::ServiceInstance;

    #[tokio::test]
    async fn test_in_memory_registry() {
        let registry = InMemoryRegistry::new();
        
        let instance = ServiceInstance::new("test-service", "127.0.0.1", 8080, "http");
        
        // 注册服务
        registry.register(instance.clone()).await.unwrap();
        
        // 发现服务
        let instances = registry.discover("test-service").await.unwrap();
        assert_eq!(instances.len(), 1);
        assert_eq!(instances[0].service_id, "test-service");
        assert_eq!(instances[0].host, "127.0.0.1");
        assert_eq!(instances[0].port, 8080);
        
        // 注销服务
        registry.deregister(instance).await.unwrap();
        let instances = registry.discover("test-service").await.unwrap();
        assert_eq!(instances.len(), 0);
    }

}